當討論到 ruby 的回傳值,nil 永遠不會缺席。到底為什麼要使用 nil?
當呼叫一個方法(如:select) 永遠都會得到一個陣列,就算 block 裡面沒有東西。
[1,2,3].select {}
# []
[1,2,3].select(&:even?)
# [2]
為什麼這個很重要?當呼叫 select 方法對陣列做事情,永遠都會得到一個陣列,而得到的結果就可以呼叫陣列方法(size, empty?, push…) 不需要檢查資料型態。這是好事!當程式碼越來越複雜但可讀性夠高可以知道當前的資料狀態可以省下許多檢查資料型態等等的時間。
當使用像是 find 方法,只會回傳單一值嗎?當元素被找的時候:
[1,2,3].find { |n| n == 2 }
# 2
當沒有符合條件的元素,find 必須回傳一些東西,可能會回傳 false。如果想要在這個回傳值上再呼叫一個方法的話,就會得到一個例外(exception)。這時候 nil 就登場了,使用 nil 是因為這是一個通用的 Null 物件,而且是拿得到的。
接下來看看 nil 使用其他方法像是 to_i, to_s & to_a 會發生什麼事。對物件使用像是 Array() & String() 是被允許的:
String(123)
# "123"
String(nil)
# ""
Array(nil)
# []
這也會有字串內插:
"abc#{nil}dfg"
字串內插(String interpolation)呼叫 to_s 就會是 block 裡面計算的結果,當有一個 #{1 + 1}
就會被轉換成2.to_s
。
現在的問題是不如你預期的 nil 出現了,可能是某個物件呼叫了本身沒有的方法而你得到了一個 NoMethodError
。
以這個例子來說,如果想要實踐 Null 物件模式,跟原本預期的東西相同。有其他的解決方法像是使用 fetch 方法帶一個預設值 & 當預設值沒有作用的時候會有一個例外(exception)。